package com.gitee.wsl.jvm.okio.sink

import com.gitee.wsl.ext.okio.base.CallState
import kotlinx.coroutines.channels.SendChannel
import okio.Buffer
import okio.ForwardingSink
import okio.Sink


/**
 * A [Sink] for counting the number of bytes uploaded.
 */
class CountingSink(
    delegate: Sink,
    private val contentLength: Long,
    private val channel: SendChannel<CallState.Uploading>
) : ForwardingSink(delegate) {

    var bytesUploaded: Long = 0

    override fun write(source: Buffer, byteCount: Long) {
        super.write(source, byteCount)
        bytesUploaded += byteCount
        emitUploadProgress()
    }

    private fun emitUploadProgress() {
        // Since the channel is CONFLATED, `trySend()` will always succeed unless the channel is
        // cancelled. If the channel is cancelled, it means that the HTTP call is cancelled, so
        // the cancellation will be notified as an IOException on `sink.write()`.
        // Therefore, the result of `trySend()` can be ignored here.
        channel.trySend(CallState.Uploading(bytesUploaded, contentLength))
    }
}
